namespace lucere.index.write
{
    /// <summary>
    /// Class that Posting and PostingVector use to write byte
    /// streams into shared fixed-size byte[] arrays.  The idea
    /// is to allocate slices of increasing lengths For
    /// example, the first slice is 5 bytes, the next slice is
    /// 14, etc.  We start by writing our bytes into the first
    /// 5 bytes.  When we hit the end of the slice, we allocate
    /// the next slice and then write the address of the new
    /// slice into the last 4 bytes of the previous slice (the
    /// "forwarding address").
    /// <para>
    /// Each slice is filled with 0's initially, and we mark
    /// the end with a non-zero byte.  This way the methods
    /// that are writing into the slice don't need to record
    /// its length and instead allocate a new slice once they
    /// hit a non-zero byte. 
    /// </para>
    /// </summary>
    public interface IByteBlockPool
    {
        byte[][] Buffers { get; set; }

        /// <summary>
        /// Which buffer we are upto
        /// </summary>
        int BufferUpTo { get; set; }
                         
        /// <summary>
        /// Where we are in head buffer
        /// </summary>
        int ByteUpTo { get; set; } 

        /// <summary>
        /// Current head buffer
        /// </summary>
        byte[] Buffer { get; set; } 
        
        /// <summary>
        /// Current head offset
        /// </summary>
        int ByteOffset { get; set; }

        void Reset();
        void NextBuffer();
        int NewSlice(int size);

        // Size of each slice.  These arrays should be at most 16
        // elements (index is encoded with 4 bits).  First array
        // is just a compact way to encode X+1 with a max.  Second
        // array is the length of each slice, ie first slice is 5
        // bytes, next slice is 14 bytes, etc.

        int[] NextLevelArray { get; set; } 
        int[] LevelSizeArray { get; set; }
        int FIRST_LEVEL_SIZE { get; set; }

        int AllocSlice(byte[] slice, int upto);
    }
}